package cn.wolfcode.luowowo.service.impl;

import cn.wolfcode.luowowo.domain.Destination;
import cn.wolfcode.luowowo.domain.Travel;
import cn.wolfcode.luowowo.query.TravelQuery;
import cn.wolfcode.luowowo.repository.TravelRepository;
import cn.wolfcode.luowowo.service.ITravelService;
import cn.wolfcode.luowowo.service.IUserInfoService;
import cn.wolfcode.luowowo.util.DBHelper;
import cn.wolfcode.luowowo.util.TravelCondition;
import com.sun.javafx.iio.ios.IosDescriptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

@Service
//@Transactional  暂时先别管事务
public class TravelServiceImpl implements ITravelService {
    @Autowired
    private IUserInfoService userInfoService;
    
    @Autowired
    private TravelRepository repository;
    
    @Autowired
    private MongoTemplate template;
    
    //目的地对象
    @Autowired
    private DestinationServiceImpl destinationService;
    @Autowired
    private ITravelService travelService;
    
    //查询单个方法
    public Travel get(String id) {
        Optional<Travel> optional = repository.findById(id);
        if (optional.isPresent()) {
            Travel travel = optional.get();
            //将目的地内容加入游记
            travel.setDest(destinationService.get(travel.getDestId()));
            //将用户对象内容加入游记
            travel.setAuthor(userInfoService.get(travel.getUserId()));
            return travel;
        }
        return null;
    }
    
    //条件查询
    //page对象里面包括: 总页数 每页显示条数......
    public Page<Travel> query(TravelQuery qo) {
        /*创建一个空的条件*/
        Query query = new Query();
    
        String destId = qo.getDestId();
    
    
        //取得天数的拼接条件
        TravelCondition day = qo.getDay();
        //如果条件不为空的话
        if (day != null) {
            //设置条件,大于等于 gte 小于等于 lte
            query.addCriteria(Criteria.where("day").gte(day.getMin()).lte(day.getMax()));
        }
        //取得旅游开销的拼接条件
        TravelCondition expend = qo.getExpend();
        if (expend != null) {
            query.addCriteria(Criteria.where("perExpend").gte(expend.getMin()).lte(expend.getMax()));
        }
        
        //如果目的地的id存在的话  就根据目的地的id查询目的地下面的游记
        if (StringUtils.hasLength(qo.getDestId())) {
            query.addCriteria(Criteria.where("destId").is(qo.getDestId()));
        }
        
        //排序的方式  一个是最新 一个是最热的排序 可以进行一起判断排序
        //最新 根据创建时间
        if (qo.getOrderType() == Travel.ORDERTYPE_NEW) {
            qo.setPageable(PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize(), Sort.Direction.DESC, "createTime"));
        }
        
        //最热 根据点击率
        if (qo.getOrderType() == Travel.ORDERTYPE_HEAT) {
            qo.setPageable(PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize(), Sort.Direction.DESC, "thumbsupnum"));
        }
        
        /*工具类传进条件后 进行数据的排序与分页*/
        Page<Travel> query1 = DBHelper.query(template, Travel.class, query, qo.getPageable());
        //查询用户的信息
        for (Travel travel : query1) {
            travel.setAuthor(userInfoService.get(travel.getUserId()));
            
            travel.setDest(destinationService.get(travel.getDestId()));
        }
        return query1;
    }
    
    /*查询全部的内容*/
    public List<Travel> list() {
        return repository.findAll();
    }
    
    
    /**
     * 删除方法
     *
     * @param id 删除的id
     */
    @Override
    public void delete(String id) {
        repository.deleteById(id);
    }
    
    /**
     * 添加与保存的方法
     *
     * @param travel
     */
    @Override
    public void saveOrUpdate(Travel travel) {
        //有部分的数据是不管添加还是编辑都是要进行添加的
        /*游记的修改时间*/
        travel.setLastUpdateTime(new Date());
        /*目的地的name*/
        travel.setDestName(destinationService.get(travel.getDestId()).getName());
        //因为保存的时候是会加上时间戳的,所以要进行分辨是新增还是编辑
        if (StringUtils.hasLength(travel.getId())) {
            //有长度是编辑 编辑的话是全量修改 所以有些数据是需要单独的修改
            //update的方法也是可以理解为  前端传过来的值是一个新的travel
            //然后从里面获取:get到需要修改的字段 (包括隐藏的需要修改的值:通过前端传的值进行查找)
            //set进原来的对象中,这样的话就不会造成未修改的值变成空值的情况
            Query query = new Query();
            /*用id作为条件进行更改*/
            query.addCriteria(Criteria.where("_id").is(travel.getId()));
            DBHelper.update(template, query, travel, "destName","state","title","coverUrl","travelTime","person","isPublic","day"
                    ,"perExpend","destId","summary","content","viewnum","replynum","favornum","sharenum","thumbsupnum");
        } else {
            //没长度是保存
            //创建的时间戳
            travel.setCreateTime(new Date());
            repository.save(travel);
        }
    }
    
    
    /**
     * 点击率前三的三个攻略
     *
     * @param destId
     * @return
     */
    @Override
    public List<Travel> selectViewnumTop3(String destId) {
        //排序条件
        PageRequest pageRequest = PageRequest.of(0, 3, Sort.Direction.DESC, "viewnum");
        //查询
        List<Travel> byDestId = repository.findByDestId(destId, pageRequest);
        
        return byDestId;
    }
    
    /**
     * 更改游记的状态
     *
     * @param id
     * @param state
     */
    @Override
    public void changeState(String id, int state) {
        //仅仅是简单的修改状态时 就将状态设置进对象就行
        Update update = new Update();
        //如果是修改审核等的状态的话 就要进行判断,是否已经审核 不管是修改什么状态,最后的修改时间都是要进行设置的
        Travel travel = this.get(id);
        //首先判断对象是否有值
        if (travel != null) {
            //travel.setLastUpdateTime(new Date());
            update.set("lastUpdateTime", new Date());
            //请求为下架 && 游记的状态为已发布状态  才可以执行下面的更新   但是拒绝也会下架发布状态的 所有后续需要做出改变
            if (state == Travel.STATE_REJECT && travel.getState() == Travel.STATE_RELEASE) {
                update.set("state", state);
            } else if (state == Travel.STATE_REJECT && travel.getState() == Travel.STATE_WAITING) {
                //请求为拒绝 && 游记的状态为待发布状态 才可以执行下面的更新
                update.set("state", state);
            } else if (state == Travel.STATE_RELEASE && (travel.getState() == Travel.STATE_WAITING || travel.getState() == Travel.STATE_REJECT)) {
                //请求为发布 && (游记的状态为待发布 || 游记的状态为拒绝) 才能进行下面的操作 并且更新发布时间
                //travel.setReleaseTime(new Date());
                update.set("releaseTime", new Date());
                update.set("state", state);
            }
        }
        Query query = new Query();
        /*修改的条件是指定的游记*/
        query.addCriteria(Criteria.where("_id").is(id));
        template.updateMulti(query, update, Travel.class);
    }
    
    /**
     * 编辑与保存的界面 如果id有值就是编辑  需要回显tv
     *
     * @param id 前端传的id
     * @return 返回一个封装了tv 与dests的map
     */
    @Override
    public Map<String, Object> selectTvAndDests(String id) {
        //先创建一个空的map
        HashMap<String, Object> map = new HashMap<>();
        //如果id有值
       if (StringUtils.hasLength(id)) {
            //回显游记的数据
            Travel travel = this.get(id);
            map.put("tv", travel);
        }
        //不管是否有值 都要回显的是目的地的对象
        List<Destination> list = destinationService.list();
        map.put("dests",list);
        //返回值
        return map;
    }
    
    @Override
    public List<Travel> findByDestName(String name) {
        List<Travel> list = repository.findByDestName(name);
        for (Travel travel : list) {
            travel.setAuthor(userInfoService.get(travel.getUserId()));
        }
        return list ;
    }
}
